package com.stylefeng.guns.modular.expenditure.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.core.common.exception.BizExceptionEnum;
import com.stylefeng.guns.core.exception.GunsException;
import com.stylefeng.guns.core.shiro.ShiroKit;
import com.stylefeng.guns.core.util.DateUtil;
import com.stylefeng.guns.modular.bank.service.IBankService;
import com.stylefeng.guns.modular.expenditure.service.IExpenditureService;
import com.stylefeng.guns.modular.system.dao.ExpenditureMapper;
import com.stylefeng.guns.modular.system.model.Bank;
import com.stylefeng.guns.modular.system.model.Expenditure;
import com.stylefeng.guns.modular.system.model.RmbCashReceipts;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  银行收支日结报表
 * </p>
 *
 * @author stylefeng123
 * @since 2018-07-02
 */
@Service
public class ExpenditureServiceImpl extends ServiceImpl<ExpenditureMapper, Expenditure> implements IExpenditureService {

    @Autowired
    private IBankService bankService;

    /**
     * 获取组装银行收支日结报表
     * @return
     * @throws GunsException
     * @author laoyu
     * @date 2018-07-26
     */
    @Override
    public Page<Expenditure> getBankday(String beginDate,String endDate,String platform,Page<Expenditure> page) throws GunsException {
        EntityWrapper<Expenditure> wrapper = new EntityWrapper<>();
        wrapper.eq("platform",platform);
        wrapper.ge("revdate",beginDate);
        wrapper.le("revdate",endDate);
        //日期排序
        wrapper.orderBy("revdate",true);
        //查询银行收支报表数据库
        Page<Expenditure> pagelist=this.selectPage(page,wrapper);
        List<Expenditure> expenditures = pagelist.getRecords();
        List<Expenditure> bankdayList = new ArrayList<>();
        //将数据库中的日结数据组装成银行日结报表数据格式
        for (Expenditure expenditure : expenditures){
            expenditure.setTotalBankDeposits(expenditure.getRecharge()+expenditure.getOtherDeposits());//银行总入款=客户充值+其他入款
            expenditure.setTotalBankWithdrawal(expenditure.getReflect()+expenditure.getFee()+expenditure.getOtherWithdrawals());//银行总出款=客户提现+手续费+其他支出
            //银行净收入=银行总入款-银行总出款
            expenditure.setNetIncomeOfBanks(expenditure.getRecharge()+expenditure.getOtherDeposits()-expenditure.getReflect()-expenditure.getFee()-expenditure.getOtherWithdrawals());
            //根据报表日期查询前一天的银行余额,银行总余额=上一天的银行余额+当天的净收入

            expenditure.setTotalBankBalance(bankService.searchOneDayBalance(expenditure.getPlatform(),DateUtil.getBeforeDay(expenditure.getRevdate()))+expenditure.getNetIncomeOfBanks());
            bankdayList.add(expenditure);
        }
        Expenditure expenditure = new Expenditure();
        try {
            expenditure.setTotalBankBalance(bankService.searchOneDayBalance(expenditure.getPlatform(), DateUtil.getBeforeDay(new SimpleDateFormat("yyyy-MM-dd").parse(beginDate))));
            bankdayList.add(0,expenditure);
        }catch (Exception e){
            throw new GunsException(BizExceptionEnum.BUSINSS_ERROR,e.getMessage());
        }
        pagelist.setRecords(bankdayList);

        return pagelist;
    }

    /**
     * 描述:导出银行第三收支报表
     * 创建人: xiang
     * 日期: 2018/8/2
     * 时间: 10:15
     */
    @Override
    public void exportExpenditure(Map<String, Object> map) {
        String platform= ShiroKit.getUser().getDeptcode();
        //查询银行收支报表数据库
        List<Expenditure> expenditures=this.selectList(new EntityWrapper<Expenditure>()
                .eq("platform",platform)
                .gt("revdate",map.get("beginDate"))
                .le("revdate",map.get("endDate"))
        );
        List<Expenditure> exportList= new ArrayList<>();
        //将数据库中的日结数据组装成银行日结报表数据格式
        for (Expenditure expenditure : expenditures){
            expenditure.setTotalBankDeposits(expenditure.getRecharge()+expenditure.getOtherDeposits());//银行总入款=客户充值+其他入款
            expenditure.setTotalBankWithdrawal(expenditure.getReflect()+expenditure.getFee()+expenditure.getOtherWithdrawals());//银行总出款=客户提现+手续费+其他支出
            //银行净收入=银行总入款-银行总出款
            expenditure.setNetIncomeOfBanks(expenditure.getRecharge()+expenditure.getOtherDeposits()-expenditure.getReflect()-expenditure.getFee()-expenditure.getOtherWithdrawals());
            //根据报表日期查询前一天的银行余额,银行总余额=上一天的银行余额+当天的净收入

            expenditure.setTotalBankBalance(bankService.searchOneDayBalance(expenditure.getPlatform(),DateUtil.getBeforeDay(expenditure.getRevdate()))+expenditure.getNetIncomeOfBanks());
            exportList.add(expenditure);
        }
        //查询开始时间的上一期余额
        if(exportList.size()>1){
            //查询月份的 上月最后一天 例:2018-07 结果2018-06-30
            Date date=DateUtil.getBeforeDay(DateUtil.parse(map.get("beginDate").toString(),"yyyy-MM"));
            double totalBankBalance=bankService.searchOneDayBalance(platform,date);
            map.put("totalBankBalance",totalBankBalance);
        }else {
            map.put("totalBankBalance",0.00);
        }
        //本月汇总
        sumMonthexpenditures(exportList,map);
        //本年汇总
        sumYearexpenditures(map.get("beginDate").toString(),map);
        //组装导出数据
        map.put("exportList",exportList);


    }
    /**
     * 描述:本月汇总
     * 创建人: xiang
     * 日期: 2018/8/2
     * 时间: 11:33
     */
    private  void sumMonthexpenditures(List<Expenditure> exportList,Map<String, Object> map){
          Expenditure sum = new Expenditure();
          for (Expenditure expenditure : exportList){
              sum.setRecharge(expenditure.getRecharge().doubleValue()
                      +(sum.getRecharge()==null ? 0:sum.getRecharge().doubleValue()));
              sum.setOtherDeposits(expenditure.getOtherDeposits().doubleValue()
                      +(sum.getOtherDeposits()==null ? 0:sum.getOtherDeposits().doubleValue()));
              sum.setReflect(expenditure.getReflect().doubleValue()
                      +(sum.getReflect()==null ? 0:sum.getReflect().doubleValue()));
              sum.setOtherWithdrawals(expenditure.getOtherWithdrawals().doubleValue()
                      +(sum.getOtherWithdrawals()==null ? 0:sum.getOtherWithdrawals().doubleValue()));
              sum.setFee(expenditure.getFee().doubleValue()
                      +(sum.getFee()==null ? 0:sum.getFee().doubleValue()));
              sum.setTotalBankDeposits(expenditure.getTotalBankDeposits().doubleValue()
                      +(sum.getTotalBankDeposits()==null ? 0:sum.getTotalBankDeposits().doubleValue()));
              sum.setTotalBankWithdrawal(expenditure.getTotalBankWithdrawal().doubleValue()
                      +(sum.getTotalBankWithdrawal()==null ? 0:sum.getTotalBankWithdrawal().doubleValue()));
              sum.setNetIncomeOfBanks(expenditure.getNetIncomeOfBanks().doubleValue()
                      +(sum.getNetIncomeOfBanks()==null ? 0:sum.getNetIncomeOfBanks().doubleValue()));
              sum.setTotalBankBalance(expenditure.getTotalBankBalance().doubleValue()
                      +(sum.getTotalBankBalance()==null ? 0:sum.getTotalBankBalance().doubleValue()));
          }
        map.put("sumMonth",sum);
    }


    /**
     * 描述:本年汇总
     * 创建人: xiang
     * 日期: 2018/8/2
     * 时间: 11:33
     */
    private  void sumYearexpenditures(String beginDate,Map<String, Object> map){
        //获取当前年份 和下一个年份
        String beginYear=DateUtil.getYear(DateUtil.parse(beginDate,"yyyy-MM-dd"));
        int endYear=Integer.valueOf(DateUtil.getYear(DateUtil.parse(beginDate,"yyyy-MM-dd"))).intValue()+1;
        Expenditure sum = this.selectOne(new EntityWrapper<Expenditure>()
                .setSqlSelect("sum(recharge) as recharge ,sum(other_deposits) AS otherDeposits,sum(reflect) as reflect,sum(other_withdrawals) AS otherWithdrawals,sum(fee) as fee")
                .eq("platform",ShiroKit.getUser().getDeptcode())
                .ge("revdate",beginYear+"-01-01")//组装2018-01-01
                .le("revdate",String.valueOf(endYear)+"-01-01")
        );
        sum.setTotalBankDeposits(sum.getRecharge()+sum.getOtherDeposits());//银行总入款=客户充值+其他入款
        sum.setTotalBankWithdrawal(sum.getReflect()+sum.getFee()+sum.getOtherWithdrawals());//银行总出款=客户提现+手续费+其他支出
        //银行净收入=银行总入款-银行总出款
        sum.setNetIncomeOfBanks(sum.getRecharge()+sum.getOtherDeposits()-sum.getReflect()-sum.getFee()-sum.getOtherWithdrawals());
        map.put("sumYear",sum);
    }


    /**
     * 描述:添加银行其他收支金额
     * 创建人: laoyu
     * 日期: 2018/8/7 0007
     * 时间: 下午 2:30
     */
    @Override
    public void addAmount(RmbCashReceipts cashReceipt) throws GunsException {


        //查询当天对应的银行日结
        EntityWrapper<Expenditure> wrapper = new EntityWrapper<>();
        wrapper.eq("platform",cashReceipt.getPlatform());
        wrapper.eq("revdate",new SimpleDateFormat("yyyy-MM-dd").format(cashReceipt.getRevdate()));
        List<Expenditure> expenditures = this.selectList(wrapper);
        if (expenditures.isEmpty()||expenditures==null){

            Expenditure expenditure = new Expenditure();
            if (cashReceipt.getType()==RmbCashReceipts.Enum_Type.支出.value) {
                if (cashReceipt.getSummary() == RmbCashReceipts.Enum_Summary.手续费.value)
                    expenditure.setFee(cashReceipt.getAmount());
                else
                    expenditure.setOtherWithdrawals(cashReceipt.getAmount());
            }else {
                expenditure.setOtherDeposits(cashReceipt.getAmount());
            }
            expenditure.setPlatform(cashReceipt.getPlatform());
            expenditure.setRevdate(cashReceipt.getRevdate());
            expenditure.setCreattime(new Date());
            expenditure.setUpdatetime(new Date());
            this.insert(expenditure);
        }else {
            Expenditure expenditure = expenditures.get(0);
            if (cashReceipt.getType()==RmbCashReceipts.Enum_Type.收款.value) {
                expenditure.setOtherDeposits(expenditure.getOtherDeposits() + cashReceipt.getAmount());
            }else {
                if (cashReceipt.getSummary() == RmbCashReceipts.Enum_Summary.手续费.value)
                    expenditure.setFee(expenditure.getFee() + cashReceipt.getAmount());
                else
                    expenditure.setOtherWithdrawals(expenditure.getOtherWithdrawals() + (cashReceipt.getAmount() == null ? 0.00 : cashReceipt.getAmount()));
            }
            expenditure.setUpdatetime(new Date());
            this.updateAllColumnById(expenditure);
        }

    }

    /**
     * 描述:删除银行其他收支金额
     * 创建人: laoyu
     * 日期: 2018/8/7 0007
     * 时间: 下午 2:30
     */
    @Override
    public void deleteAmount(RmbCashReceipts cashReceipt) throws GunsException {
        //查询银行收支日结对应的数据
        EntityWrapper<Expenditure> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("platform",cashReceipt.getPlatform());
        entityWrapper.eq("revdate",new SimpleDateFormat("yyyy-MM-dd").format(cashReceipt.getRevdate()));
        List<Expenditure> expenditures = this.selectList(entityWrapper);
        if (expenditures.isEmpty()||expenditures==null)
            throw new GunsException(BizExceptionEnum.BUSINSS_ERROR,"未找到银行收支日结表当天对应的数据");
        Expenditure expenditure = expenditures.get(0);
        if (cashReceipt.getType()==RmbCashReceipts.Enum_Type.支出.value) {
            if (cashReceipt.getSummary() == RmbCashReceipts.Enum_Summary.手续费.value)
                expenditure.setFee(expenditure.getFee() - cashReceipt.getAmount());
            else
                expenditure.setOtherWithdrawals(expenditure.getOtherWithdrawals() - cashReceipt.getAmount());
        }else {
            expenditure.setOtherDeposits(expenditure.getOtherDeposits() - cashReceipt.getAmount());
        }
        expenditure.setUpdatetime(new Date());
        this.updateById(expenditure);

    }

    /**
     * 描述:修改银行其他收支金额
     * 创建人: laoyu
     * 日期: 2018/8/7 0007
     * 时间: 下午 3:26
     */
    @Override
    public void updateAmount(RmbCashReceipts oldCashReceipt, RmbCashReceipts cashReceipt) throws GunsException {


        //查询银行收支日结对应的数据
        EntityWrapper<Expenditure> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("platform",cashReceipt.getPlatform());
        entityWrapper.eq("revdate",new SimpleDateFormat("yyyy-MM-dd").format(oldCashReceipt.getRevdate()));
        List<Expenditure> expenditures = this.selectList(entityWrapper);
        if (expenditures.isEmpty()||expenditures==null)
            throw new GunsException(BizExceptionEnum.BUSINSS_ERROR,"未找到银行收支日结表当天对应的数据");
        Expenditure expenditure = expenditures.get(0);
        if (cashReceipt.getType()==RmbCashReceipts.Enum_Type.支出.value) {
            if (cashReceipt.getSummary() == RmbCashReceipts.Enum_Summary.手续费.value)
                expenditure.setFee(expenditure.getFee() + cashReceipt.getAmount() - oldCashReceipt.getAmount());
            else
                expenditure.setOtherWithdrawals(expenditure.getOtherWithdrawals() + cashReceipt.getAmount() - oldCashReceipt.getAmount());
        }else {
            expenditure.setOtherDeposits(expenditure.getOtherDeposits() + cashReceipt.getAmount() - oldCashReceipt.getAmount());
        }
        expenditure.setUpdatetime(new Date());
        this.updateById(expenditure);
    }



    /**
     * 描述:银行收支日结页面合计
     * 创建人: xiang
     * 日期: 2018/8/8
     * 时间: 16:55
     */
    @Override
    public Expenditure total( Wrapper<Expenditure> wrapper) throws GunsException {

        wrapper.setSqlSelect("IFNULL(sum(recharge),0) as recharge  ,IFNULL(sum(other_deposits),0) AS otherDeposits," +
                "IFNULL(sum(reflect),0) as reflect,\n" +
                "IFNULL(sum(other_withdrawals),0) AS otherWithdrawals,IFNULL(sum(fee),0) as fee ,max(revdate) as revdate");
        //查询银行收支报表数据库
        Expenditure expenditure=this.selectOne(wrapper);
        DecimalFormat df = new DecimalFormat("#0.00");
            expenditure.setTotalBankDeposits(expenditure.getRecharge()+expenditure.getOtherDeposits());//银行总入款=客户充值+其他入款
            expenditure.setTotalBankWithdrawal(expenditure.getReflect()+expenditure.getFee()+expenditure.getOtherWithdrawals());//银行总出款=客户提现+手续费+其他支出
            //银行净收入=银行总入款-银行总出款
            String netIncomeOfBank=df.format(expenditure.getRecharge()+expenditure.getOtherDeposits()-expenditure.getReflect()-expenditure.getFee()-expenditure.getOtherWithdrawals());
            expenditure.setNetIncomeOfBanks(Double.valueOf(netIncomeOfBank));
            //根据报表日期查询前一天的银行余额,银行总余额=上一天的银行余额+当天的净收入
            if(expenditure.getRevdate()!=null){
                String totalBankBalance=df.format(bankService.searchOneDayBalance(expenditure.getPlatform(),DateUtil.getBeforeDay(expenditure.getRevdate()))
                        +expenditure.getNetIncomeOfBanks());
                expenditure.setTotalBankBalance(Double.valueOf(totalBankBalance));
            }


        return expenditure;
    }
}
